package com.jinzheng.qhwocket.commont;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.jinzheng.qhwocket.entity.UserSocket;
import com.jinzheng.qhwocket.service.UserSocketService;
import com.jinzheng.qhwocket.util.GBT32960Decoder;
import io.netty.buffer.Unpooled;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.tomcat.util.buf.HexUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.util.*;

/**
 * socket接受客户端线程，根据参数接受，多次接受
 */
public class ServerReceiveParaThread implements Runnable {

    private Socket socket;
    private GBT32960Decoder gbt32960Decoder;
    private static Logger log = LoggerFactory.getLogger(ServerReceiveParaThread.class);

    public ServerReceiveParaThread(Socket socket, GBT32960Decoder gbt32960Decoder) {
        this.socket = socket;
        this.gbt32960Decoder = gbt32960Decoder;
    }

    @Override
    public void run(){
        try {
            socket.setSoTimeout(10);//设置socket读超时时间10毫秒
            InputStream inputStream = socket.getInputStream();
            byte[] bytes = new byte[1024];
            int value = inputStream.read(bytes);
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            out.write(bytes,0,value);
            socket.shutdownInput();
            byte[] toByteArray = out.toByteArray();
            List<Object> finalList = new ArrayList<>();
            gbt32960Decoder.decode(null, Unpooled.copiedBuffer(toByteArray),finalList);
            System.out.println("接受服务器字节数据："+toByteArray);
            if(CollectionUtils.isNotEmpty(finalList)){
                for (Object object:finalList){
                    byte[] object1 = (byte[]) object;
                    log.info("客户端数据："+ HexUtils.toHexString(object1));
                    boolean checkCode = checkCode(object1);
                    System.out.println("数据校验结果："+checkCode);
                    if(checkCode){
                        new SendData(object1).invoke();
                    }
                }
                finalList.clear();
            }
            log.info("客户端传来的数据："+new String(bytes,0,value, StandardCharsets.UTF_8));
            OutputStream outputStream = socket.getOutputStream();
            outputStream.write(bytes,0,value);
            log.info("服务端关闭客户端[{}]", socket.getRemoteSocketAddress());
            outputStream.close();
            outputStream.close();
        } catch (Exception e) {
            log.info("接收数据异常socket关闭");
            try {
                socket.close();
            } catch (IOException e1) {
                e1.printStackTrace();
            }
            e.printStackTrace();
        } finally {
            log.info("数据要怎么保留");
        }

    }

    /**
     * 十六进制转十进制
     * @param content
     * @return
     */
    public static int covert(String content){
        int number=0;
        String [] HighLetter = {"A","B","C","D","E","F"};
        Map<String,Integer> map = new HashMap<>();
        for(int i = 0;i <= 9;i++){
            map.put(i+"",i);
        }
        for(int j= 10;j<HighLetter.length+10;j++){
            map.put(HighLetter[j-10],j);
        }
        String[]str = new String[content.length()];
        for(int i = 0; i < str.length; i++){
            str[i] = content.substring(i,i+1);
        }
        for(int i = 0; i < str.length; i++){
            number += map.get(str[i])*Math.pow(16,str.length-1-i);
        }
        return number;
    }


    /**
     * 数据校验
     * @param bytes
     * @return
     */
    public static boolean checkCode(byte[] bytes){
        if(null==bytes || bytes.length < 25 || bytes[0]!=0x23 || bytes[1]!=0x23){
            log.warn("数据格式错误：{}",HexUtils.toHexString(bytes));
            return false;
        }
        byte checkCode = 0x00;
        for (byte bt:bytes){
            checkCode ^= bt;
        }
        if(checkCode!=0x00){
            log.warn("数据校验错误：{}",HexUtils.toHexString(bytes));
            return false;
        }
        return true;
    }

    private static byte[] stringToByte (String strings) {
        byte[] result=new byte[strings.length()/2];
        for (int i = 0; i <= strings.length(); i += 2) {
            result[i/2]=(byte) (charToInt(strings.charAt(i))*16+charToInt(strings.charAt(i+1)));
        }
        return result;
    }
    private static int charToInt(char ch) {
        if (ch >= 65 && ch <= 70) {
            return ch - 55;
        } else if (ch >= 97 && ch <= 102) {
            return ch - 87;
        } else {
            return ch;
        }
    }

    public static void main(String[] args) {
        String value = "232301FE393031323835303730303030303030303001001E160C0F0B061B000438393836303242363033313730303230313830340100A5";
        byte[] stringToByte = stringToByte(value);
        boolean checkCode = checkCode(stringToByte);
        System.out.println(checkCode);
    }

    /**
     * 发送数据
     */
    private class SendData {
        private byte[] object1;

        public SendData(byte... object1) {
            this.object1 = object1;
        }

        public void invoke() {
            KafkaTopicNameProp kafkaTopicNameProp = SpringUtil.getBean(KafkaTopicNameProp.class);
            String topicName = StringUtils.EMPTY;
            if(null!=kafkaTopicNameProp && StringUtils.isNotBlank(kafkaTopicNameProp.getTopicName())){
                topicName = kafkaTopicNameProp.getTopicName();
            }else{
                topicName = "JZQH_SOCKET_RECEIVE_VALUE";
            }
            String openstoreType = StringUtils.EMPTY;
            if(null!=kafkaTopicNameProp && StringUtils.isNotBlank(kafkaTopicNameProp.getOpenstoreType())){
                openstoreType = kafkaTopicNameProp.getOpenstoreType();
            }else{
                openstoreType = "storedb";
            }
            System.out.println(String.format("发送kafka监听topicName：%s，存储方式：%s",topicName,openstoreType));
            if("storekafka".equals(openstoreType)){
                KafkaProducer kafkaProducer = SpringUtil.getBean(KafkaProducer.class);
                String toJSONString = JSONObject.toJSONString(HexUtils.toHexString(object1), SerializerFeature.WriteMapNullValue);
                //kafkaProducer.sendMessageByTopic(topicName,null, JSONObject.toJSONString(object1, SerializerFeature.WriteMapNullValue));
                kafkaProducer.sendMessageByTopic(topicName,null, toJSONString);
            }else{
                String toJSONString = JSONObject.toJSONString(HexUtils.toHexString(object1), SerializerFeature.WriteMapNullValue);
                UserSocketService userSocketService = SpringUtil.getBean(UserSocketService.class);
                UserSocket userSocket = new UserSocket();
                userSocket.setTopicName(topicName);
                userSocket.setHeaderName("test_socket_header");
                userSocket.setNote(toJSONString);
                userSocket.setStatus(0);
                userSocket.setCreateTime(LocalDateTime.now());
                userSocketService.save(userSocket);
            }
        }
    }
}
